#include <stdint.h>
#include <stdio.h>
#include "stm32f4xx_hal.h"


typedef struct
{
	GPIO_TypeDef *gpio;
	uint16_t tx_pin;
	uint16_t rx_pin;
	USART_TypeDef *uartNo;
} Uart_GPIO_t;

static Uart_GPIO_t g_UartGpioList = {GPIOA, GPIO_PIN_9, GPIO_PIN_10, USART1};

// 串口接收中断优先级
#define USART1_IRA_PRIORITY	(2)
// 串口句柄
UART_HandleTypeDef huart1 = { 0 };
// 串口接收回调函数
void (*pProcess)(UART_HandleTypeDef *huart);

/**
***********************************************************
* @brief 串口硬件初始化
* @param baudRate:波特率
* @return 
***********************************************************
*/
void Uart_DrvInit(uint32_t baudRate)
{
	GPIO_InitTypeDef GPIO_Init = { 0 };
	
	if(baudRate < 1200) return; // 限制波特率最小值要大于1200
		
	/* 配置串口使用到的GPIO */
	__HAL_RCC_GPIOA_CLK_ENABLE();
	
	GPIO_Init.Mode = GPIO_MODE_AF_PP;
	GPIO_Init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	GPIO_Init.Pin = g_UartGpioList.tx_pin; // TX引脚配置
	GPIO_Init.Alternate = GPIO_AF7_USART1;
	HAL_GPIO_Init((GPIO_TypeDef *)g_UartGpioList.gpio, &GPIO_Init);
	
	GPIO_Init.Mode = GPIO_MODE_AF_PP;
	GPIO_Init.Pull = GPIO_NOPULL;
	GPIO_Init.Pin = g_UartGpioList.rx_pin; // RX引脚配置
	HAL_GPIO_Init((GPIO_TypeDef *)g_UartGpioList.gpio, &GPIO_Init);
	
	
	/* 配置串口参数 */
	__HAL_RCC_USART1_CLK_ENABLE();
	
	huart1.Instance = g_UartGpioList.uartNo;
	huart1.Init.BaudRate = baudRate;
	huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
	huart1.Init.Mode = UART_MODE_TX_RX;
	huart1.Init.Parity = UART_PARITY_NONE;
	huart1.Init.StopBits = UART_STOPBITS_1;
	huart1.Init.OverSampling = UART_OVERSAMPLING_16;
	huart1.Init.WordLength = UART_WORDLENGTH_8B;
	HAL_UART_Init(&huart1);
	
	/* 配置串口中断相关 */
	__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);
	HAL_NVIC_SetPriority(USART1_IRQn, USART1_IRA_PRIORITY, 0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);
}

/**
***********************************************************
* @brief 串口发送一个字节
* @param ch:待发送的字节
* @return 
***********************************************************
*/
void Uart_SendByte(uint8_t ch)
{
	while((USART1->SR&0X40) == 0);
	USART1->DR = ch;
}

/**
***********************************************************
* @brief 串口发送字符串数组
* @param pbuf:字符串数组首地址
* @param len:字符串长度
* @return 
***********************************************************
*/
void Uart_SendString(uint8_t *pbuf, uint32_t len)
{
	if((NULL == pbuf) || len <= 0) return;
	
	for(int i = 0; i < len; i++)
	{
		Uart_SendByte(pbuf[i]);
	}
}

/**
***********************************************************
* @brief 串口接收中断回调函数
* @param huart:串口句柄
* @return 
***********************************************************
*/
void RegisterProcess(void (*pfunc)(UART_HandleTypeDef *huart))
{
	pProcess = pfunc;
}

/**
***********************************************************
* @brief 串口接收中断回调函数
* @param huart:串口句柄
* @return 
***********************************************************
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	pProcess(huart);
}

/**
***********************************************************
* @brief 重定向printf输出到串口1
* @param ch:待发送的字符
* @param f:文件流
* @return 
***********************************************************
*/
int fputc(int ch, FILE *f)
{
	while((USART1->SR&0X40) == 0); // 等待发送缓冲区为空
	USART1->DR = (uint8_t)ch;
	return ch;
}
